﻿using System;
using System.Windows.Forms;
using Lib;
using Lib.VirtualDesktopAPI;
using System.Text.Json;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace Edog2487
{
    public partial class Form1 : Form
    {
        Hook hook;
        // 消息分发器
        Func<string, string> messageDispatcher;
        // 消息处理器
        Dictionary<string, Func<WsMessage, WsMessage>> messageHandlerMap;

        //private WebSocketServer ws;
        bool isTest = false;
        bool isFromTauri = false;
        // 父进程pid
        int parentPid;
        string os;
        // 最后接收到ws 消息的时间
        //private long lastPingTime;

        private Icon blank = Properties.Resources.blank;
        private Icon normal = Properties.Resources.normal;
        private Icon normal_recording = Properties.Resources.normal1;
        private bool _status = false;
        string[] args = null;

        public Form1()
        {
            InitializeComponent();
            initWsMsgHandler();
           
        }

        
        public Form1(string[] args)
        {
            InitializeComponent();
            this.args = args;
            initWsMsgHandler();

            if (args.Length >= 1)
            {

                this.isTest = args[0].Equals("testxuejianxinokok");
                this.isFromTauri = args[0].Equals("fromTauri20240807");
                if (args.Length >= 2) { 
                  // 获取父进程pid
                  this.parentPid = Convert.ToInt32(args[1]);
                }
            }
            initButtons();


            // 调试用
            if (this.isTest)
            {
                Lib.ProcessManager.AllocConsole();
                Console.WriteLine("The parentPid is: {0}", parentPid);
            }
            stopHook();
           
            // 默认启动hook
            if (args.Length >= 3 && args[2].Equals("true"))
            {
                startHook();
            }
        }

        private void initButtons()
        {
            if (this.isFromTauri || !this.isTest)
            {
                this.btSendMsg.Enabled = false;
                this.btStartHook.Enabled = false;
                this.btStopHook.Enabled = false;
                this.btStartWS.Enabled = false;
                this.btStopWS.Enabled = false;
            }

            if (this.isFromTauri)
            {
               // btStartWS_Click(null, null);
            }
            notifyIcon1.Icon = blank;
        }

        /// <summary>
        /// 初始化消息处理器
        /// </summary>
        private void initWsMsgHandler()
        {
            hook = new Hook();
            hook.Close();
            System.Timers.Timer timer = new System.Timers.Timer(1000);//1秒钟的时间间隔
            timer.Elapsed += this.OnTimedEvent;
            timer.AutoReset = true;//重复执行
            timer.Enabled = true;//启动定时器
            //lastPingTime = DateTime.Now.Ticks;

            messageDispatcher = this.WsMessageDispatcher;
            messageHandlerMap = new Dictionary<string, Func<WsMessage, WsMessage>>
            {
                // Kind 对应的处理器
                { "test", this.testMsgHandler },
                { "startHook", this.startHookMsgHandler },
                { "stopHook", this.stopHookMsgHandler },
                { "getDesktopCount", this.getDesktopCountMsgHandler },
                { "killProcess", this.killProcessMsgHandler },
                { "checkProcess", this.checkProcessMsgHandler },
                { "checkEnv",this.checkEnvMsgHandler },
                { "startRecording", this.startRecordingHandler },
            };

            // 启动后台线程以处理控制台输入输出
            StartConsoleCommunication();

        }


        // 后台线程处理标准输入输出
        private void StartConsoleCommunication()
        {
            // 启动一个新的线程来处理标准输入输出
            var thread = new System.Threading.Thread(ProcessConsoleInput);
            thread.IsBackground = true;  // 让它在应用关闭时自动退出
            thread.Start();
        }

        // 处理标准输入输出的方法
        private void ProcessConsoleInput()
        {
            try
            {
               
                using (StreamReader reader = new StreamReader(Console.OpenStandardInput(), Encoding.UTF8))
                using (StreamWriter writer = new StreamWriter(Console.OpenStandardError(), Encoding.UTF8) { AutoFlush = true })
                {
                   

                    while (true)
                    {
                        // 从标准输入读取数据
                        string receivedMessage = reader.ReadLine();

                        // 调试控制台输出,stderr已经重定向 ,可以用stdout 输出
                        if (this.isTest)
                        {
                           Console.WriteLine(receivedMessage);
                        }

                        if (receivedMessage == null)
                        break;
                       
                        // 调用消息处理器
                        string result = this.WsMessageDispatcher(receivedMessage);
                        // 模拟处理输入并返回结果
                        writer.WriteLine(result);

                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }

        private  void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
        {
            //超过15s 没有消息 直接退出
            //long timeout = (DateTime.Now.Ticks  - lastPingTime)/ TimeSpan.TicksPerMillisecond;
            // Console.WriteLine("定时器事件触发，当前时间{0},timeout={1}", DateTime.Now.ToString(), timeout);
            //if (timeout > 60_000)
            //{   // 1 分钟后自动退出
            //    ExitMenuItem_Click(null, null);
            //} else 
            //if (ws != null){
            //    long timeout = (DateTime.Now.Ticks - ws.getLastMsgTime()) / TimeSpan.TicksPerMillisecond;
            //    if (timeout > 10_000)
            //    {
            //        _status = false;
            //    }
            //}

            if (Lib.ProcessManager.IsProcessRunning(this.parentPid))
            {
                _status = true;
            }
            else
            {
                ExitMenuItem_Click(null, null);
            }


            if (_status)
            {
                notifyIcon1.Icon = normal;
            }
            else
            {
                notifyIcon1.Icon = blank;
            }

        }


        private string WsMessageDispatcher(string msg)
        {
            //Console.WriteLine($"Received message: {msg}");
            _status = true;
            // 设置最后消息接收时间
            //lastPingTime = DateTime.Now.Ticks;
            if (!msg.StartsWith("{")) return msg;

            //1.反序列化
            WsMessage wsMessage = JsonSerializer.Deserialize<WsMessage>(msg);
            WsMessage reply = new WsMessage();
            //2.调用消息处理函数
            if (this.messageHandlerMap.ContainsKey(wsMessage.Kind))
            {
                reply = this.messageHandlerMap[wsMessage.Kind].Invoke(wsMessage);

            }
            //3.反序列化
            string jsonString = JsonSerializer.Serialize(reply);
            return jsonString;

        }

        private WsMessage testMsgHandler(WsMessage wsMessage)
        {
            WsMessage reply = new WsMessage();
            reply.Id = wsMessage.Id;
            reply.Content = wsMessage.Content;
            return reply;
        }
        private WsMessage startHookMsgHandler(WsMessage wsMessage)
        {
            int hookId = 0;
            // 在UI主线程中安装钩子,否则钩子失效
            this.Invoke((MethodInvoker)(() =>
            {
                 hookId = startHook();
            }));

            WsMessage reply = new WsMessage();
            reply.Id = wsMessage.Id;
            reply.Content = hookId.ToString();
            return reply;
        }

        private WsMessage startRecordingHandler(WsMessage wsMessage)
        {
            notifyIcon1.Icon = normal_recording;
            //Console.WriteLine("startRecording:{0}, {1} ", wsMessage.Id, wsMessage.Content);
            WsMessage reply = new WsMessage();
            reply.Id = wsMessage.Id;
            reply.Content = null;
            return reply;
        }

        private WsMessage stopHookMsgHandler(WsMessage wsMessage)
        {
            int hookId = stopHook();
            WsMessage reply = new WsMessage();
            reply.Id = wsMessage.Id;
            reply.Content = hookId.ToString();
            return reply;
        }
        private WsMessage getDesktopCountMsgHandler(WsMessage wsMessage)
        {
            if (null == os)
            {
                Version version = Environment.OSVersion.Version;
                os = Loader.GetImplementationForOS();
            }

            WsMessage reply = new WsMessage();
            reply.Id = wsMessage.Id;
            try
            {
                IVirtualDesktopManager vdm = Loader.LoadImplementationWithFallback(os);
                //Console.WriteLine("WindowsVersion:{0},os :{1} ,VirtualDesktop: {2}", version.ToString(), os, vdm.DisplayCount());
                reply.Content = vdm.DisplayCount().ToString();
            }
            catch (Exception _e)
            {
                reply.Content = "0";
            }
            return reply;
        }

        private WsMessage killProcessMsgHandler(WsMessage wsMessage)
        {
            String[] processNames = wsMessage.Content.Split(';');
            StringBuilder sb = new StringBuilder();
            foreach (var processName in processNames)
            {
                var count = Lib.ProcessManager.KillAll(processName);
                sb.Append(processName).Append(":").Append(count).Append(";");
            }

            WsMessage reply = new WsMessage();
            reply.Id = wsMessage.Id;
            reply.Content = sb.ToString();
            return reply;
        }

        private WsMessage checkProcessMsgHandler(WsMessage wsMessage)
        {
            String[] processNames = wsMessage.Content.Split(';');
            StringBuilder sb = new StringBuilder();
            foreach (var processName in processNames)
            {
                var isRunning = Lib.ProcessManager.IsProcessRunning(processName);
                sb.Append(processName).Append(":").Append(isRunning?1:0).Append(";");
            }

            WsMessage reply = new WsMessage();
            reply.Id = wsMessage.Id;
            reply.Content = sb.ToString();
            return reply;
        }

        private WsMessage checkEnvMsgHandler(WsMessage wsMessage)
        {
            WsMessage reply = new WsMessage();
            reply.Id = wsMessage.Id;
            reply.Content = Lib.OS.PreCheckPass().ToString();
            //reply.Content = false.ToString();
            return reply;
        }



        private void btClose_Click(object sender, EventArgs e)
        {

            ExitMenuItem_Click(null, null);

        }

        
        private void btStartWS_Click(object sender, EventArgs e)
        {

            //ws = new WebSocketServer(this.messageDispatcher);
            //_ = ws.StartServer("localhost", 24824);
        }

        private void btStopWS_Click(object sender, EventArgs e)
        {
            //if (ws != null)
            //{
            //    ws.Stop();
            //    ws = null;
            //}

        }

        private void btSendMsg_Click(object sender, EventArgs e)
        {
            //if (ws != null)
            //{
            //    _ = ws.SendMessage("===========fromc#");
            //}
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //不想让程序在任务栏中显示，请把窗体的属性ShowInTaskbar设置为false
            this.ShowInTaskbar = false;
            this.WindowState = FormWindowState.Minimized;
            this.Hide();


            this.notifyIcon1.Visible = true;
            this.notifyIcon1.ContextMenuStrip = new ContextMenuStrip();
            if (!this.isFromTauri)
            {
                // 添加菜单项到 ContextMenuStrip
                ToolStripMenuItem showFormMenuItem = new ToolStripMenuItem("显示窗体");
                showFormMenuItem.Click += ShowFormMenuItem_Click;
                this.notifyIcon1.ContextMenuStrip.Items.Add(showFormMenuItem);
            }

            ToolStripMenuItem exitMenuItem = new ToolStripMenuItem("退出");
            exitMenuItem.Click += ExitMenuItem_Click;
            this.notifyIcon1.ContextMenuStrip.Items.Add(exitMenuItem);

        }


        private void ShowFormMenuItem_Click(object sender, EventArgs e)
        {
            // 显示窗体
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void ExitMenuItem_Click(object sender, EventArgs e)
        {
            btSendMsg_Click(null, null);
            btStopHook_Click(null, null);
            Thread.Sleep(1000);
            Lib.ProcessManager.StopFFmpeg();
            try
            {
                // 杀死父进程
                Process.GetProcessById(this.parentPid).Kill();
            }
            catch (Exception )
            {

            }
            // 退出应用程序
            Application.Exit();
        }

        private int startHook()
        {
           
            hook = new Hook();
            hook.Close();
            return hook.Start();
        }

        private int stopHook()
        {
            int hookId = 0;
            if (null != hook)
            {
                 hookId = hook.Close();
                // hook.Dispose();
               
            }
            return hookId;
        }


        private void btStartHook_Click(object sender, EventArgs e)
        {
            startHook();
        }

        private void btStopHook_Click(object sender, EventArgs e)
        {
            stopHook();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {

            ExitMenuItem_Click(null, null);
            
            //notifyIcon1.ShowBalloonTip(2000, "提示", "应用程序已最小化到通知区域", ToolTipIcon.Info);

        }

        


    }
}
